<template>
  <el-card style="margin: 10px" v-show="visible"
           v-loading.fullscreen.lock="loading"
           element-loading-text="拼命加载中"
           element-loading-spinner="el-icon-loading"
           element-loading-background="rgba(0, 0, 0, 0.8)">

    <el-form :model="spuInfo" :rules="rules" ref="form">
      <el-form-item label="spu名称" label-width="100px" prop="spuName">
        <el-input v-model="spuInfo.spuName"></el-input>
      </el-form-item>

      <el-form-item label="品牌" label-width="100px" prop="tmId">
        <el-select  placeholder="请选择" v-model="spuInfo.tmId">
          <el-option v-for="tm in trademarkList"
                     :label="tm.tmName" :value="tm.id"></el-option>
        </el-select>
      </el-form-item>

      <el-form-item label="spu描述" label-width="100px" prop="description">
        <el-input  type="textarea" :rows="3" v-model="spuInfo.description"
                   placeholder="请输入内容">
        </el-input>
      </el-form-item>

      <el-form-item label="spu图片" label-width="100px" prop="spuImageList" ref="spuImageList">
        <el-upload
          action="/dev-api/admin/product/fileUpload"
          list-type="picture-card"
          :file-list="spuInfo.spuImageList"
          :on-success="handlePictureCardSuccess"
          :on-preview="handlePictureCardPreview"
          :on-remove="handlePictureCardRemove">
          <i class="el-icon-plus"></i>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible">
          <img width="100%" :src="dialogImageUrl" >
        </el-dialog>
      </el-form-item>

      <el-form-item label="销售属性" label-width="100px" prop="spuSaleAttrList">
        <el-select  :placeholder="saleAttrPlaceholder"
                    style="margin-right: 10px" v-model="saleAttr">
          <el-option v-for="baseSaleAttr in unUsedBaseSaleAttrList"
                     :label="baseSaleAttr.name"
                     :value="`${baseSaleAttr.id}-${baseSaleAttr.name}`"></el-option>
        </el-select>
        <el-button type="primary" icon="el-icon-circle-plus"
                   @click="addSpuSaleAttr" :disabled="!saleAttr"
                   style="margin-bottom: 10px" >
          添加销售属性
        </el-button>
        <el-table :data="spuInfo.spuSaleAttrList" border>
          <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
          <el-table-column prop="saleAttrName" label="属性名" width="250"  align="center"></el-table-column>
          <el-table-column  label="属性值名称列表"  align="center">
            <template slot-scope="{row,$index}">
              <el-tag :key="tag.id" v-for="(tag,index) in row.spuSaleAttrValueList" closable
                :disable-transitions="false" @close="handleClose(row,index)">
                {{tag.saleAttrValueName}}
              </el-tag>
              <el-input  class="input-new-tag" v-if="row.inputVisible"
                         v-model="row.inputValue" size="small"
                         :ref="`saveTagInput-${$index}`"
                         @keydown.enter.native="handleInputConfirm(row,$index)"
                         @blur="handleInputConfirm(row,$index)"></el-input>
              <el-button v-else class="button-new-tag" size="small"
                         @click="showInput(row,$index)">+ New Tag</el-button>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="300"  align="center">
            <!--在输入框按回车按钮 通过keyup注册 会 el-popconfirm的弹窗  解决方案:换keydown-->
            <template slot-scope="{row,$index}">
              <el-popconfirm :title="`确定要删除${row.saleAttrName}吗？`"
                             @onConfirm="delSpuSaleAttr($index)">
                <TipButton content="删除SPU" placement="top" effect="light"
                           size="mini" type="danger" icon="el-icon-delete" slot="reference">
                </TipButton>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>

      <el-form-item label-width="100px">
        <el-button type="primary"  style="margin-bottom: 10px"
                   @click="save" :loading="loadingForSave">保存</el-button>
        <el-button @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script>
  import _ from "lodash"
  export default {
    name: "addOrUpdate",
    props:["visible"],
    data(){
      //销售属性的验证规则  不但销售属性数组得有值 而且每一个销售属性必须得拥有值才算验证通过
      function validatePass(rule, value, callback){
        // value : 当前验证字段的值(spuSaleAttrList的值)
        // callback: 决定验证通不通过;
        //    callback()代表验证通过
        //    callback(new Error("xxx")):代表验证不通过
        if(value.length <= 0){
          callback(new Error("必须选中一个销售属性"))
        }else{
          //每一个销售属性都必须拥有值列表!!!
          let flag = value.every(item => item.spuSaleAttrValueList.length>0)
          if(flag){
            callback()
          }else{
            callback(new Error("销售属性必须拥有值"))
          }
        }
      }
      return {
        baseSaleAttrList:[],//所有的销售属性列表
        trademarkList:[],//所有的品牌列表
        spuInfo:{}, //spu基本信息; 既要做数据回显 又要做数据收集

        //收集的销售属性
        saleAttr:"",

        //图片上传相关数据
        dialogImageUrl: '',
        dialogVisible: false,

        //咬重复逻辑的狗
        dog:false,
        //save按钮的loading效果
        loadingForSave:false,
        //获取品牌 销售属性的loading效果
        loading:false,

        //表单验证相关的数据
        rules:{
          spuName: [{ required: true, message: '请输入spu名称', trigger: 'blur' }],
          description:[{ required: true, message: '请输入spu描述', trigger: 'blur' }],

          tmId:[{ required: true, message: '请选择品牌', trigger: 'change' }],
          spuImageList:[{ required: true, message: '请选择一张图片', trigger: 'change' }],
          spuSaleAttrList:[{ validator: validatePass, trigger: 'change' }]
        }
      }
    },
    computed:{
      // 销售属性下拉列表的显示文案
      saleAttrPlaceholder(){
        return `还有${this.unUsedBaseSaleAttrList.length}个未选择`
      },
      // 销售属性下拉列表的值
      unUsedBaseSaleAttrList(){
        //从所有的销售属性列表中 剔除 spu已经拥有的销售属性列表
        return this.baseSaleAttrList.filter((baseSaleAttr)=>{
          //baseSaleAttr : 一个个基础的销售属性
          //this.spuInfo.spuSaleAttrList : spu已经拥有的销售属性列表
          //baseSaleAttr 存在于 this.spuInfo.spuSaleAttrList 要剔除掉 需要返回false
          //baseSaleAttr 不存在于 this.spuInfo.spuSaleAttrList 要保留下来 需要返回true

          //只要some的回调有一次返回true some方法就返回true
          //只有some的所有回调都返回false some方法也返回false
          return !this.spuInfo.spuSaleAttrList.some((spuSaleAttr)=>{
            //spuSaleAttr : 一个个spu已经拥有的销售属性
            return  +spuSaleAttr.baseSaleAttrId === +baseSaleAttr.id
          })
        })
      }
    },
    methods:{
      //点击保存按钮的逻辑
      save(){
        this.$refs.form.validate(async (valid) => {
          if (valid) {
            //验证通过
            this.loadingForSave = true;
            //准备修改请求的数据
            let spuInfo = this.spuInfo;
            spuInfo.spuImageList = spuInfo.spuImageList.map(({name,url})=>({imgName:name,imgUrl:url}));
            //发送修改请求
            const {code} = await this.$api.product.spu.addOrUpdateSpu(spuInfo);
            if(code === 200){
              //1. 修改成功的提醒
              this.$message.success("操作成功");
              //2. 关闭修改界面 刷新列表界面
              this.cancel()
              this.$emit("success")
            }
            this.loadingForSave = false;
          }
        });
      },

      //初始化数据 initData这个方法在每次从spulist界面跳转到addOrUpdate界面时都会调用!
      async initData(spuInfo,category3Id){
        this.loading = true;
        /*spuInfo
          category3Id: 61,                    spu所处的三级分类
          description: "Apple iPhone 12",     spu的描述
          id: 3,                              spu的标识id
          spuImageList: null,                 spu的图片列表 但是分页时没有返回
          spuName: "Apple iPhone 12"          spu的名称
          spuSaleAttrList: null               spu的销售属性列表 但是分页时没有返回
          tmId: 2                             spu的品牌id
        */
        //接收spu基本信息
        this.spuInfo = _.cloneDeep(spuInfo);
        //防止el-upload报错
        this.spuInfo.spuImageList = [];
        this.spuInfo.spuSaleAttrList = [];
        //获取所有的品牌列表
        const {code:tmCode,data:trademarkList} = await this.$api.product.spu.getBaseTrademark();
        if(tmCode===200){
          this.trademarkList = trademarkList;
        }
        //获取所有的销售属性
        const {code:baseSaleCode,data:baseSaleAttrList} = await this.$api.product.spu.getBaseSaleAttrList();
        if(baseSaleCode===200){
          this.baseSaleAttrList = baseSaleAttrList
        }

        if(JSON.stringify(spuInfo) === "{}"){
            //新增
          this.spuInfo.category3Id = category3Id;
        }else{
            //修改
          //获取spu的图片列表
          const {code:imageCode,data:spuImageList} = await this.$api.product.spu.getSpuImageList(spuInfo.id);
          if(imageCode===200){
            this.spuInfo.spuImageList = spuImageList.map((image)=>({
              name:image.imgName,
              url:image.imgUrl,
            }));
          }
          //获取spu对应的销售属性
          const {code:spuSaleCode,data:spuSaleAttrList} = await this.$api.product.spu.getSpuSaleAttrList(spuInfo.id);
          if(spuSaleCode===200){
            /* spuSaleAttrList:[
                 {
                     baseSaleAttrId:1
                     id:5
                     saleAttrName:"颜色"
                     spuId:3
                     spuSaleAttrValueList:[
                       {
                         baseSaleAttrId:1
                         id:12
                         isChecked:null
                         saleAttrName:"颜色"
                         saleAttrValueName:"白色"
                         spuId:3
                       }
                     ]
                  }
                  ....
             ]*/
            this.spuInfo.spuSaleAttrList = spuSaleAttrList
          }
        }

        this.loading = false;
      },

      //取消按钮的逻辑
      cancel(){
        this.$emit("update:visible",false)
      },
      //添加销售属性
      addSpuSaleAttr(){
        // 构建一个销售属性
        /*
          {
            "baseSaleAttrId": "1",
            "saleAttrName": "选择颜色",
            "spuSaleAttrValueList": [
              {
                "saleAttrValueName": "白色",
                "baseSaleAttrId": "1"
              }
            ]
          }
        */
        const [baseSaleAttrId,saleAttrName] = this.saleAttr.split("-");
        const spuSaleAttr = {
          baseSaleAttrId,
          saleAttrName,
          spuSaleAttrValueList:[]
        };
        this.saleAttr = "";
        this.spuInfo.spuSaleAttrList.push(spuSaleAttr)
      },
      //删除销售属性
      delSpuSaleAttr(index){
        this.spuInfo.spuSaleAttrList.splice(index,1)
      },

      //tag相关方法
      handleClose(row,index) {
        //tag : 属性值对象
        row.spuSaleAttrValueList.splice(index,1)
      },
      showInput(row,index) {
        if(this.dog){return}
        this.$set(row,"inputVisible",true)
        this.$nextTick(_ => {
            this.$refs[`saveTagInput-${index}`].focus()
        });
      },
      handleInputConfirm(row,index) {
        let inputValue = row.inputValue;

        //输入重复时 有报错提醒
        this.dog = row.spuSaleAttrValueList.filter((spuSaleAttr)=>{
          return spuSaleAttr.saleAttrValueName === inputValue
        }).length >=1
        if(this.dog){
          this.$message.error("属性值不能重复")
          //重新获取焦点
          this.$refs[`saveTagInput-${index}`].focus()
          return;
        }
        this.dog = false;

        if (inputValue) {
          //收集属性值
          row.spuSaleAttrValueList.push({
            saleAttrValueName:inputValue,
            baseSaleAttrId:row.baseSaleAttrId
          })
        }
        row.inputVisible = false;
        row.inputValue = '';
      },

      //图片上传相关方法
      handlePictureCardSuccess(response, file, fileList){
        this.spuInfo.spuImageList = fileList;
        //清除之前的验证提示
        this.$refs.spuImageList.clearValidate()
      },
      handlePictureCardRemove(file, fileList) {
        //file : 当前我们删除中的图片的基本信息
        //fileList: 剩下的图片所组成的数组
        this.spuInfo.spuImageList = fileList;
      },
      handlePictureCardPreview(file) {
        // file: 当前我们选中的图片的基本信息
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
    }
  }
</script>

<style scoped>

</style>
